/*!
  @file   VectorTypes.hpp
  @author Hamza Hutchinson
  @date   04/26/2009
  @brief  
    Unit tests for vector types.
*/
#include "VectorTypes_Test.hpp"
#include "../Source/VectorTypes.hpp"

#include <iostream>
#include <cmath>

namespace VectorTest
{

  typedef bool (*TestFunc)(void);


  void TestALL()
  {
    TestALLVec2();
    TestALLVec3();
    TestALLVec4();
  }

  //Vector2D tests
  void TestALLVec2()
  {
  }

  //Vector3D tests
  bool TestVec3_00() // operator==
  {
    VectorTypes::Vector3D v1(1, 2, 3);
    VectorTypes::Vector3D v2(1, 2, 3);

    return v1 == v2;
  }

  bool TestVec3_01() // constructors
  {
    float v[] = { 1.23f, 4.56f, 7.89f };

    VectorTypes::Vector3D v1(v);
    VectorTypes::Vector3D v2(v[0], v[1], v[2]);

    return v1 == v2;
  }

  bool TestVec3_02() // Set
  {
    VectorTypes::Vector3D v(1.23f, 4.56f, 7.89f);
    VectorTypes::Vector3D v1;
    VectorTypes::Vector3D v2;

    v1.Set(v);
    v2.Set(v.x, v.y, v.z);

    return v1 == v2;
  }

  bool TestVec3_03() // assignment
  {
    VectorTypes::Vector3D v1(1.23f, 4.56f, 7.89f);
    VectorTypes::Vector3D v2;
    v2 = v1;

    return v1 == v2;
  }

  bool TestVec3_04() // operator!=
  {
    VectorTypes::Vector3D v1(1, 2, 3);
    VectorTypes::Vector3D v2(4, 5, 6);

    return v1 != v2;
  }

  bool TestVec3_05() // operator[]
  {
    VectorTypes::Vector3D v(1, 2, 3);

    return (v.x == v[0]) && (v.y == v[1]) && (v.z == v[2]);
  }

  bool TestVec3_06() // GetArrayPtr
  {
    VectorTypes::Vector3D v(1, 2, 3);

    return (v.GetArrayPtr()[0] == v[0]) && (v.GetArrayPtr()[1] == v[1]) && (v.GetArrayPtr()[2] == v[2]);
  }

  bool TestVec3_07() // operator+ (binary)
  {
    VectorTypes::Vector3D v1(1, 1, 1);
    VectorTypes::Vector3D v2 = v1 + v1;

    return (v2.x == 2) && (v2.y == 2) && (v2.z == 2);
  }

  bool TestVec3_08() // operator- (binary)
  {
    VectorTypes::Vector3D v1(1, 1, 1);
    VectorTypes::Vector3D v2 = v1 - v1;

    return (v2.x == 0) && (v2.y == 0) && (v2.z == 0);
  }

  bool TestVec3_09() // operator- (unary)
  {
    VectorTypes::Vector3D v1(1, 2, 3);
    VectorTypes::Vector3D v2 = -v1;

    return (v1.x == -(v2.x)) && (v1.y == -(v2.y)) && (v1.z == -(v2.z));
  }

  bool TestVec3_10() // operator+=
  {
    VectorTypes::Vector3D v1(1, 1, 1);
    VectorTypes::Vector3D v2(1, 1, 1);
    v2 += v1;

    return (v2.x == 2) && (v2.y == 2) && (v2.z == 2);
  }

  bool TestVec3_11() // operator-=
  {
    VectorTypes::Vector3D v1(1, 1, 1);
    VectorTypes::Vector3D v2(1, 1, 1);
    v2 -= v1;

    return (v2.x == 0) && (v2.y == 0) && (v2.z == 0);
  }

  bool TestVec3_12() // operator* (scaler)
  {
    VectorTypes::Vector3D v1(1, 1, 1);
    VectorTypes::Vector3D v2;
    v2 = 2 * v1;

    return (v2.x == 2) && (v2.y == 2) && (v2.z == 2);
  }

  bool TestVec3_13() // operator* (scaler)
  {
    VectorTypes::Vector3D v1(1, 1, 1);
    VectorTypes::Vector3D v2;
    v2 = v1 * 2;

    return (v2.x == 2) && (v2.y == 2) && (v2.z == 2);
  }

  bool TestVec3_14() // operator/
  {
    VectorTypes::Vector3D v1(1, 1, 1);
    VectorTypes::Vector3D v2(1, 1, 1);
    v2 = v1 / 2;

    return (v2.x == .5f) && (v2.y == .5f) && (v2.z == .5f);
  }

  bool TestVec3_15() // operator*= (scaler)
  {
    VectorTypes::Vector3D v(1, 1, 1);
    v *= 2;

    return (v.x == 2) && (v.y == 2) && (v.z == 2);
  }

  bool TestVec3_16() // operator/=
  {
    VectorTypes::Vector3D v(1, 1, 1);
    v /= 2;

    return (v.x == .5f) && (v.y == .5f) && (v.z == .5f);
  }

  bool TestVec3_17() // Length
  {
    VectorTypes::Vector3D v1(5, 0, 0);
    VectorTypes::Vector3D v2(0, 5, 0);
    VectorTypes::Vector3D v3(0, 0, 5);
    VectorTypes::Vector3D v4(1, 1, 1);

    return (v1.Length() == 5) && 
           (v2.Length() == 5) && 
           (v3.Length() == 5) && 
           (v4.Length() == sqrt(3.f));
  }

  bool TestVec3_18() // LengthSquared
  {
    VectorTypes::Vector3D v1(5, 0, 0);
    VectorTypes::Vector3D v2(0, 5, 0);
    VectorTypes::Vector3D v3(0, 0, 5);
    VectorTypes::Vector3D v4(1, 1, 1);

    return (v1.LengthSquared() == 25) && 
           (v2.LengthSquared() == 25) && 
           (v3.LengthSquared() == 25) && 
           (v4.LengthSquared() == 3);
  }

  bool TestVec3_19() // Normalize
  {
    VectorTypes::Vector3D v(6, 2, 5);
    v.Normalize();

    return (v.Length() == 1);
  }

  bool TestVec3_20() // Normalized
  {
    VectorTypes::Vector3D v1(6, 2, 5);
    VectorTypes::Vector3D v2 = v1.Normalized();
    v1.Normalize();

    return (v1 == v2);
  }

  bool TestVec3_21() // IsZeroLength
  {
    VectorTypes::Vector3D v(.000000001f, .000000001f, .000000001f);

    return v.IsZeroLength(.0001f);
  }

  bool TestVec3_22() // operator^ (cross)
  {
    VectorTypes::Vector3D v1(1, 0, 0);
    VectorTypes::Vector3D v2(0, 1, 0);
    VectorTypes::Vector3D v3(0, 0, 1);

    VectorTypes::Vector3D x = v2 ^ v3;
    VectorTypes::Vector3D y = v3 ^ v1;
    VectorTypes::Vector3D z = v1 ^ v2;

    return (v1 == x) && (v2 == y) && (v3 == z);
  }

  bool TestVec3_23() // operator* (dot)
  {
    VectorTypes::Vector3D x(1, 0, 0);
    VectorTypes::Vector3D y(0, 1, 0);
    VectorTypes::Vector3D z(0, 0, 1);

    return (x * y == 0) &&
           (x * z == 0) &&
           (y * z == 0);
  }

  bool TestVec3_24() // operator* (dot)
  {
    VectorTypes::Vector3D v1(1, 3, 2);
    VectorTypes::Vector3D v2(3, 12, 4);
    VectorTypes::Vector3D v3 = v1 ^ v2;

    return (v3 * v1 == 0) && (v3 * v2 == 0);
  }

  void TestALLVec3()
  {
    TestFunc tests[] = { TestVec3_00,
                         TestVec3_01,
                         TestVec3_02,
                         TestVec3_03,
                         TestVec3_04,
                         TestVec3_05,
                         TestVec3_06,
                         TestVec3_07,
                         TestVec3_08,
                         TestVec3_09,
                         TestVec3_10,
                         TestVec3_11,
                         TestVec3_12,
                         TestVec3_13,
                         TestVec3_14,
                         TestVec3_15,
                         TestVec3_16,
                         TestVec3_17,
                         TestVec3_18,
                         TestVec3_19,
                         TestVec3_20,
                         TestVec3_21,
                         TestVec3_22,
                         TestVec3_23,
                         TestVec3_24 };
    int numTests = sizeof(tests) / sizeof(TestFunc);

    for(int i = 0; i < numTests; ++i)
    {
      if(!(tests[i]()))
        std::cout << "Test " << i << " Failed." << std::endl;
    }
  }

  //Vector4D tests
  void TestALLVec4()
  {
  }

}//namespace VectorTest
